package com.example.lib_common.http

import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch


fun <T> LifecycleOwner.httpRequest(
    apiFun: suspend () -> HttpResponse<T>, callBack: (BaseRequestCallback<T>.() -> Unit) = {}
) {
    httpRequest(apiFun, lifecycleScope, callBack)
}

fun <T> ViewModel.httpRequest(
    apiFun: suspend () -> HttpResponse<T>, callBack: (BaseRequestCallback<T>.() -> Unit) = {}
) {
    httpRequest(apiFun, viewModelScope, callBack)
}

fun <T> ViewModel.liveRequest(
    apiFun: suspend () -> HttpResponse<T>, block: (BaseRequestCallback<T>.() -> Unit)
): LiveData<T?> {
    val liveData = MutableLiveData<T?>()
    val callback = BaseRequestCallback<T>().apply { block.invoke(this) }

    httpRequest(apiFun, viewModelScope) {
        onStart = callback.onStart
        onFailed = callback.onFailed
        onFinally = callback.onFinally
        onCancelled = callback.onCancelled
        onFailToast = callback.onFailToast
        onSuccess = { data ->
            liveData.value = data
            callback.onSuccess?.invoke(data)
        }
    }
    return liveData
}

fun <T> httpRequest(
    apiFun: suspend () -> HttpResponse<T>,
    coroutineScope: CoroutineScope,
    callback: BaseRequestCallback<T>.() -> Unit
) {
    // 先创建 callback
    val mCallback = BaseRequestCallback<T>().apply(callback)

    mCallback.onStart()  // 请求开始回调

    coroutineScope.launch {
        val result = try {
            val response = apiFun()
            if (response.isSuccessful()) {
                Result.success(response.data)
            } else {
                Result.failure(
                    ReactiveHttpException(message = response.errorMsg)
                )
            }
        } catch (e: Exception) {
            Result.failure(
                ReactiveHttpException(message = e.message)
            )
        }

        if (!isActive) {
            mCallback.onCancelled?.invoke()
            return@launch
        }

        result.fold(onSuccess = { data ->
            mCallback.onSuccess?.let { onSuccessFunc ->
                onSuccessFunc(data)
            }
        }, onFailure = { ex ->
            val exception =
                ex as? ReactiveHttpException ?: ReactiveHttpException(message = ex.message)
            if (mCallback.onFailed != null) {
                mCallback.onFailed?.let { onFailFunc ->
                    onFailFunc(exception)
                }
            } else if (mCallback.onFailToast()) {
//                        Toast.makeText(App.instance, exception.message ?: "请求失败", Toast.LENGTH_SHORT).show()
            }
        })
        mCallback.onFinally()
    }
}

